﻿using System;
using System.Collections.Generic;
using System.Xml;

namespace ConfigManager.Core
{
    public class XmlInstruction
    {
        private XmlInstruction _parentInstruction = null;
        private XmlDocument _xmlDoc;
        private XmlNode _node;
        private string _condition;

        #region Properties
        /// <summary>
        /// Gets or sets the XML document.
        /// </summary>
        /// <value>The XML document.</value>
        protected XmlDocument XmlDoc
        {
            get { return _xmlDoc; }
            set { _xmlDoc = value; }
        }

        /// <summary>
        /// Gets or sets the XML node.
        /// </summary>
        /// <value>The XML node.</value>
        public XmlNode Node
        {
            get { return _node; }
            set { _node = value; }
        }

        /// <summary>
        /// Gets or sets the condition.
        /// </summary>
        /// <value>The condition.</value>
        public string Condition
        {
            get { return _condition; }
            set { _condition = value; }
        }

        /// <summary>
        /// Gets or sets the parent instruction.
        /// </summary>
        /// <value>The parent instruction.</value>
        public XmlInstruction ParentInstruction
        {
            get { return _parentInstruction; }
            set { _parentInstruction = value; }
        }
        #endregion

        /// <summary>
        /// Initializes a new instance of the <see cref="XmlInstruction"/> class.
        /// </summary>
        /// <param name="xmlDoc">The XML doc.</param>
        /// <param name="node">The node.</param>
        /// <param name="parameters">The parameters.</param>
        /// <param name="data">The data.</param>
        protected XmlInstruction(XmlDocument xmlDoc, XmlNode node, IDictionary<string, string> parameters)
        {
            if (xmlDoc == null)
                throw new ArgumentNullException("xmlDoc");

            if (node == null)
                throw new ArgumentNullException("node");

            if (parameters == null)
                throw new ArgumentNullException("parameters");

            this.XmlDoc = xmlDoc;
            this.Node = node;

            if (parameters.ContainsKey("condition"))
                this.Condition = parameters["condition"];
        }

        /// <summary>
        /// Runs this instruction.
        /// </summary>
        public virtual void Run()
        {
            DeleteNode(Node);
        }

        /// <summary>
        /// Passeses the conditions.
        /// </summary>
        /// <returns></returns>
        protected bool PassesConditions()
        {
            if (string.IsNullOrEmpty(Condition))
                return true;
            else
                return Interpreter.Eval(Condition);
        }

        /// <summary>
        /// Inserts the XML fragment.
        /// </summary>
        /// <param name="xmlData">The XML data.</param>
        /// <param name="location">The location.</param>
        /// <param name="xmlDoc">The XML doc.</param>
        protected void InsertXmlFragment(string xmlData, XmlNode location, XmlDocument xmlDoc)
        {
            XmlDocumentFragment frag = xmlDoc.CreateDocumentFragment();
            frag.InnerXml = xmlData;
            location.ParentNode.InsertAfter(frag, location);
        }

        /// <summary>
        /// Deletes the XML node.
        /// </summary>
        /// <param name="node">The XML node.</param>
        protected void DeleteNode(XmlNode node)
        {
            node.ParentNode.RemoveChild(node);
        }
    }
}
